#include "tinyxml.h"
#include <sstream>
#include <unistd.h>
#include <iostream>

#include "misc.hpp"
#include "cconffile.hpp"
#include "debug.hpp"

using namespace wheels;
/*
当前代码的版本号。这个版本号和文件中的VER字段对应
*/
static const char *CONFIG_FILE_VERSION = "1.0";

CConfFile::CPathTravler :: CPathTravler( const std::string& path , CConfFile* conf , TiXmlElement* current )
{
	(void)current;
	if( conf == nullptr ){
		p_file = nullptr;
		ERROR_MSG( "DOM对象无效" );
		debug::printCallstack();
		throw ERR_DOM_OBJ;
	}

	p_current = conf->p_root;
	p_rst = p_current;
	p_file = conf;

	parse_path( path );       //
	run();
}

TiXmlElement* CConfFile ::
CPathTravler :: operator()()
{
	return p_rst;
}

TiXmlElement* CConfFile::CPathTravler :: operator()( const std::string& path )
{
	m_path_data.erase( m_path_data.begin() , m_path_data.end() );
	if( parse_path( path ) == 0 )
		run();
	return p_rst;
}


int CConfFile::CPathTravler :: parse_path( const std::string& path )
{
	int ret = 0;
	std::string str = path, tmp_str;

	if( path.empty() ){
		return PATH_DATA_EMPTY;
	}

    	m_path_data.erase( m_path_data.begin() , m_path_data.end() );

	do{
		size_t pos;
		pos = str.find( '/' );
		if( pos != std::string::npos ){
			if( pos != 0 )//是子目录
				tmp_str = str.substr( 0 , pos );
			else tmp_str.clear();//是根目录
			//拆分字符串，分成已经解析的和没有解析的
			str = str.substr( pos + 1 , std::string::npos );
			//将目录路径存储路径表
			if( tmp_str.empty() && !str.empty())//生成根目录路径
				tmp_str = "/";
			m_path_data.push_back( tmp_str );
		}
		else{//找不到'/'说明是叶子节点或者空节点
			if( str.empty() == false ){//是叶子节点，将叶子节点存入路径
				//表中。完成目录查找
				m_path_data.push_back( str );
				str.clear();
			}
		}
	}while( str.empty() == false );

    	return ret;
}

int CConfFile::CPathTravler :: run()
{
	int ret = OK;
	p_rst = NULL;
	ArrayPath::iterator it = m_path_data.begin();
	if( it == m_path_data.end() ){
		ret = PATH_DATA_EMPTY;
	}
	for(; it < m_path_data.end() && ret == OK; ++it ){
		if( (*it) == "." ) continue;                        //忽略本地操作符号
		else if( (*it) == "/") ret = go_to_root();          //移动到根目录
		else if( (*it) == ".." ) ret = go_to_parent();      //移动到父目录
		else if( it != m_path_data.end() -- )               //移动到子目录
			ret = go_to_child((*it));
		else{                                               //移动到目标
			ret = go_to_brother( (*it));
		}
	}
	return ret;
}

TiXmlElement* CConfFile::CPathTravler :: Cd( const std::string& path )
{
	parse_path( path );

	run();

	return p_current;
}


int CConfFile::CPathTravler :: go_to_parent( )
{
	int ret = OK;
	if( p_current){
		if( p_current->Parent() ){  // 不是根结点
			p_current = (TiXmlElement*)(p_current->Parent());
		}else{
			if( p_file )
				p_current = p_file->p_root;
		}
	}else{
		if( p_file )
			p_current = p_file -> p_root;
	}



	return ret;
}

int CConfFile::CPathTravler :: go_to_root()
{
	int ret = OK;
	if( p_file )
		p_current = p_file->p_root;

	return ret;
}

int CConfFile::CPathTravler :: go_to_child( const std::string& child )
{
	std::string str , str1;
	int ret = 0;
	if( p_current )
		p_current = p_current->FirstChildElement();
	if( p_current != NULL ){
		while( p_current != NULL ){
			const char * c_str = p_current->Value();
			if( c_str == nullptr ){
				p_rst = NULL;
				return ERR_GET_NAME;
			}
			str1.assign( c_str );

			if( str1 != "dir" && str1 != "var"){
				p_current = NULL;
				p_rst = NULL;
				return ERR_FILE_DIR_FORMAT;
			}
			c_str = p_current->Attribute("name");
			if( c_str == nullptr ){
				ERROR_MSG( "Can't find attribute name" );
				p_rst = NULL;
				return ERR_GET_ATTR;
			}
			str.assign( c_str );
			if( str == child ){
				ret = 0;
				p_rst = p_current;
				return ret;
			}
			p_current = p_current->NextSiblingElement();
		}

		if( p_current == NULL ){
			p_rst = NULL;
			ret = PATH_NOT_EXIST;
		}else{
			ret = OK;
		}
	}else{
		ret = PATH_NOT_EXIST;
		p_rst = NULL;
	}
	return ret;
}

int CConfFile::CPathTravler :: go_to_brother( const std::string& bro )
{
	std::string str;
	int ret = 0;

	if( p_current != NULL ){
		while( p_current != NULL ){
			const char * c_str = p_current->Attribute("name");
			if( c_str == nullptr ){
				ERROR_MSG( "Can't find attribute name" );
				p_rst = NULL;
				return ERR_GET_ATTR;
			}
			str.assign( c_str );
			if( str == bro ){
				ret = 0;
				break;
			}
			p_current = p_current->NextSiblingElement();
		}
		if( p_current == NULL ){
			p_rst = NULL;
			ret = PATH_NOT_EXIST;
			ERROR_MSG( bro  + " 不存在." );
		}else{
			ret = OK;
		}
	}
	else{
		ret = PATH_NOT_EXIST;
		p_rst = NULL;
	}

	return ret;
}

CConfFile :: CConfFile( const std::string& file ):m_file()
{
	if( access( file.c_str() , F_OK ) != 0 ){
        throw std::runtime_error("配置文件不存在");
	}
	m_doc.LoadFile( file );
	if( m_doc.Error() == false ){
		p_root = m_doc.FirstChildElement();//获取根节点
		p_current = p_root;
		if( p_root == nullptr ){//获取根节点失败
			MSG_1( "CConfFile( const std::string& file ) : 无法获取根节点 %s" , TRED , file.c_str() );
			throw std::runtime_error( "无法获取根节点" ); //CAN_NOT_FIND_XML_ROOT;
		}else{//调整根节点位置
			if( check_file() ){
				//TODO , 留在将来调整文件根指针位置或者做其他调整
			}else{
				MSG_1( "CConfFile( const std::string& file ) : 无法载入文件 %s" , TRED , file.c_str() );
                throw std::runtime_error( "无法载入文件" ); //CAN_NOT_LOAD_FILE;
			}
		}
	}else{//装入文件失败
		MSG_1( "CConfFile( const std::string& file ) : 无法载入文件 %s" , TRED , file.c_str() );
        throw std::runtime_error( "无法载入文件" ); //CAN_NOT_LOAD_FILE;
	}
}

void CConfFile :: Cd( const std::string& path )
{
	CPathTravler trler( path , this , p_current );

	p_current = trler();
}

bool CConfFile :: check_file()
{
	bool ret = true;
	const char * str = p_root->Value();
	if( str == nullptr ){
		MSG( "CConfFile( const std::string& file ) : 无法获取根节点值, 配置文件格式错误" , TRED );
		return false;
	}
	//文件根目录存在
	std::string root = str;
	if( root != "CONF_FILE" ){          //检查文件版本号
		return false;
	}
	const char * ver = p_root->Attribute("VER");
	if( ver == nullptr ){
		MSG( "CConfFile( const std::string& file ) : 无法获取版本号, 配置文件格式错误" , TRED );
		return false;
	}
	root = ver;
	if(  root != "1.0" ){
		MSG_1( "CConfFile( const std::string& file ) : 版本号 %s 错误, 配置文件格式错误" , TRED , str );
		return false;
	}
	
	return ret;
}

TiXmlElement* CConfFile ::find_var( const std::string& name )
{
	// 这个函数是能否支持分级目录的关键函数之一。
	// 为了能够让文件支持分支结构，这个函数必须能够进行树结构遍历功能
	// 在目前版本0的情况下，只支持平坦结构的变量定义
	TiXmlElement* ret = NULL;//p_root->FirstChildElement();
	CPathTravler trler( name , this , p_current );

	ret = trler();

	return ret;
}

CConfFile :: ~CConfFile(){}

bool CConfFile::has( const std::string& var )
{
	TiXmlElement * obj = find_var( var );
	return obj != nullptr;
}

bool CConfFile :: SetValue( const std::string& var , const std::string& v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , const std::string& v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
	if( obj != nullptr ){
		if( strcmp( obj->Attribute( "type" ) , "string" ) == 0 ){
			obj->SetAttribute( "value" , v );
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , const std::string& v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;
}

bool CConfFile :: SetValue( const std::string& var , int v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , int v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var );

	if( obj != nullptr ){
		auto str = std::to_string( v );
		if( strcmp(obj->Attribute("type") , "int" ) == 0 )
			obj->SetAttribute( "value" , str );
		else{
			MSG_1( "CConfFile::SetValue( const std::string& var , int v ) : 变量 %s 类型不是 int" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , int v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;	
}


bool CConfFile :: SetValue( const std::string& var , bool v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , bool v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var );

	if( obj != nullptr ){
		if( strcmp( obj->Attribute( "type" ), "bool" ) == 0 ){
			if( v )
				obj->SetAttribute( "value" , "true" );
			else
				obj->SetAttribute( "value" , "false" );
		}else{
			MSG_1( "CConfFile::SetValue( const std::string& var , bool v ) : 变量 %s 类型不是 bool" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , bool v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;	
}

bool CConfFile :: SetValue( const std::string& var , long v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , long v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var );

	if( obj != nullptr ){
		if( strcmp( obj->Attribute("type") , "int" ) == 0 ){
			auto str = std::to_string( v );

			obj->SetAttribute( "value" , str );
		}else{
			MSG_1( "CConfFile::SetValue( const std::string& var , long v ) : 变量 %s 类型不是 int" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , long v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;	
}


bool CConfFile::SetValue( const std::string& var , float v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , float v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var );

	if( obj != nullptr ){
		if( strcmp( obj->Attribute("type") , "float" ) == 0 ){
			auto str = std::to_string( v );

			obj->SetAttribute( "value" , str );
		}else{
			MSG_1( "CConfFile::SetValue( const std::string& var , float v ) : 变量 %s 类型不是 float" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , float v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;	
}

bool CConfFile::SetValue( const std::string& var , double v )
{
	if( var.empty() ){
		MSG_1( "CConfFile::SetValue( const std::string& var , double v ) : 变量名不能为空 %s" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var );

	if( obj != nullptr ){
		if( strcmp( obj->Attribute("type") , "float" ) == 0 ){
			auto str = std::to_string( v );

			obj->SetAttribute( "value" , str );
		}else{
			MSG_1( "CConfFile::SetValue( const std::string& var , double v ) : 变量 %s 类型不是 float" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "CConfFile::SetValue( const std::string& var , double v ) : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;	
}

bool CConfFile::AddDir( const std::string& dir )
{
	bool ret = true;
	if( has( dir ) ){
		MSG_1( "AddDir() : 目录 %s 已经存在" , TNORMAL , dir.c_str() );
		ret = true;
	}

	std::vector< std::string > dirs;
	split( dir , '/' , dirs );
	std::string path = "/" , path_parent = "";
	for( auto& d : dirs ){ // 遍历目录路径,创建目录节点.这个方法可以创建多级目录.
		path_parent = path;
		path += d + "/";
		if( !has( path ) ){
			TiXmlElement * p = find_var( path_parent );
			TiXmlElement dir( "dir" );
			dir.SetAttribute( "name" , d );
			p->InsertEndChild( dir );
		}
	}
	return ret;
}


bool CConfFile :: AddValue( const std::string& var , const std::string& v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
	if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{
        TiXmlElement p( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "string" );
        p.SetAttribute( "value" , v );
        obj->InsertEndChild( p );
	}
	return ret;
}
bool CConfFile :: AddValue( const std::string& var , int v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
    if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{
        TiXmlElement p( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "int" );
        std::stringstream ss;
        ss << v;
        p.SetAttribute( "value" , ss.str() );
        obj->InsertEndChild( p );
	}
	return ret;
}
bool CConfFile :: AddValue( const std::string& var , long v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
    if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{

        TiXmlElement p( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "int" );
        auto str = std::to_string(v);
        p.SetAttribute( "value" , str );
        obj->InsertEndChild( p );
    }
	return ret;
}
bool CConfFile :: AddValue( const std::string& var , bool v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
    if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{
        TiXmlElement p( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "string" );
        if( v )
            p.SetAttribute( "value" , "true" );
        else
            p.SetAttribute( "value" , "false" );

        obj->InsertEndChild( p );
	}
	return ret;
}
bool CConfFile :: AddValue( const std::string& var , float v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
	if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{
        TiXmlElement p( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "string" );
        std::stringstream ss;
        ss << v;
        p.SetAttribute( "value" , ss.str() );
        obj->InsertEndChild( p );
	}
	return ret;
}
bool CConfFile :: AddValue( const std::string& var , double v )
{
	bool ret = true;
	if( var.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}
	TiXmlElement * obj = find_var( var );
	if( obj != nullptr ){			// 指定的变量名称不能已经存在
		MSG_1( "AddValue() : 变量 %s 已经存在" , TNORMAL , var.c_str() );
		return false;
	}
	std::string   dir , name;
	size_t pos = var.find_last_of( "/" );
	if( pos == std::string::npos ){
		MSG_1( "AddValue() : 变量名称 %s 格式错误" , TRED , var.c_str() );
		return false;
	}
	dir = var.substr( 0 , pos );
	name = var.substr( pos + 1 );
	if( name.empty() ){
		MSG_1( "AddValue() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	obj = find_var( dir );

    if( obj == nullptr ){			// 指定的变量路径不存在
		MSG_1( "AddValue() : 目录 %s 不存在" , TRED , dir.c_str() );
		return false;
	}else{
        TiXmlElement p( "var" );// = new TiXmlElement( "var" );
        p.SetAttribute( "name" , name );
        p.SetAttribute( "type" , "string" );
        std::stringstream ss;
        ss << v;
        p.SetAttribute( "value" , ss.str() );
        obj->InsertEndChild( p );
	}
	return ret;
}

bool CConfFile :: is_var( TiXmlElement * node )
{
	std::string   value;
	bool ret = false;

	const char * d = node->Value();
	if( d ){
		std::string str = d;
		if( str == "var" ) ret = true;
	}else{
		MSG_1( "is_var() : 节点 %s 为空" , TRED , d );
		return false;
	}

	return ret;
}
bool CConfFile :: Del( const std::string& var , bool del_ch )
{
	if( var.empty() ){
		MSG_1( "Del() : 变量名称 %s 为空" , TRED , var.c_str() );
		return false;
	}

	TiXmlElement * obj = find_var( var ) , * parent = nullptr;
	parent = reinterpret_cast<TiXmlElement*>( obj->Parent() );
	if( obj ){
		try{
			if( is_var( obj ) ){// 是变量，则直接删除
				if( parent == nullptr ){
					MSG_1( "Del() : 变量 %s 为根节点，不能删除" , TRED , var.c_str() );
					return false;
				}else{
					if( !parent->RemoveChild( obj ) ){
						MSG_1( "Del() : 删除变量 %s 失败" , TRED , var.c_str() );
						return false;
					}
				}
			}else{ // 是目录，则根据预设
				if( del_ch ){  // 删除所有的子节点
					TiXmlElement * child = obj->FirstChildElement() , * child1 = nullptr;
					std::string child_var;
					while( child ){
						child1 = child->NextSiblingElement();
						child_var = var + "/" + child->Attribute("name");
						Del( child_var , del_ch );		// 递归执行删除操作
						child = child1;
					}// else
				}else if( obj->NoChildren()== true && !parent->RemoveChild( obj ) ){ // 如果无子节点则直接删除
					MSG_1( "Del() : 删除目录 %s 失败" , TRED , var.c_str() );
					return false;	
				}// if ( del_ch ) else
			}// if( is_var ) else
		}catch( err_code e ){
			MSG_1( "Del() : 变量 %s 不存在" , TRED , var.c_str() );
			return false;
		}
	}else{
		MSG_1( "Del() : 变量 %s 不存在" , TRED , var.c_str() );
		return false;
	}
	return true;
}

std::string 
CConfFile :: errMsg( emErrCode e )
{
	std::string ret;
	switch( e ){
	case CAN_NOT_LOAD_FILE:
        ret = "载入配置文件失败.";
		break;
	case ERR_FILE_NOT_EXIST:
        ret = "配置文件不存在";
		break;
	case CAN_NOT_FIND_XML_ROOT:
        ret = "找不到XML根节点，配置文件格式错误.";//无法找到XML根节点
		break;
	case ERROR_FILE_VERSION:                 //文件版本错误
        ret = "文件版本错误.";
		break;
	case ERROR_FILE_FORMAT:                  //文件格式错误
        ret = "文件格式错误.";
		break;
	case ERROR_FILE_ROOT_NAME:
        ret = "文件根节点名称错误";               //文件跟节点名称错误
		break;
	case ERROR_VAR_NO_NAME:                  //变量没有名称
        ret = "变量名称无效.";
		break;
	case ERROR_VAR_VALUE_TYPE:               //变量类型不匹配
        ret = "变量类型不匹配.";
		break;
	case ERROR_FILE_DIR_FORMAT:
        ret = "文件格式错误";
		break;
	case ERROR_VAR_NOT_EXIST:                // 变量不存在
        ret = "变量不存在.";
		break;
	case ERROR_SAVE_FILE:
        ret = "保存配置文件失败.";
		break;
	case ERR_PATH_GRRAMA:                    // 路径格式错误
        ret = "路径格式错误";
		break;
    case ERR_VAR_NAME_EMPTY:                 // 变量名称空
        ret = "变量名称不能和为空.";
		break;
	case ERR_PATH_NOT_EXIST:                 // 路径不存在
        ret = "路径不存在;";
		break;
	case ERR_DEL_ROOT:                       // 执行了删除根节点的操作
        ret = "不能删除根节点";
		break;
	case ERR_OBJ_NULL:
        ret = "对象不能为NULL";
		break;
	default: ret = ""; break;
	}
	debug::printCallstack();
	return ret;
}

CConfFile :: e_error_conf_file
CConfFile :: Save()
{
	if( m_doc.SaveFile() )
		return OK;
	return ERROR_SAVE_FILE;
}

CConfFile :: e_error_conf_file
CConfFile :: Save( const std::string& file )
{
	FILE * fp = fopen( file.c_str() , "w" );
	if( fp ){
		if( m_doc.SaveFile( fp ) ){
			fclose( fp );
			delete this;
			return OK;
		}else{
		}
	}else{
        MSG_1( "写入配置文件 %s 操作失败。" , TRED , file.c_str() );
	}

	return ERROR_SAVE_FILE;
}

